module executor.group.GroupExecutor;

import msgtrans;
import message.Constants;
import message.MsgDefine;
import google.protobuf;
import hunt.logging;
import std.array;
import std.conv : to;
import hunt.util.Serialize;
import client.GateServerClient;
import client.MsgServerClient;
import service.GroupService;
import service.ApplyService;
import service.SearchUserService;
import bootstrap.DatabaseBootstrap;
import core.stdc.time;
import hunt.framework;

/**
群功能模块
**/

@TransportServer(LogicServerName)
class GroupExecutor : AbstractExecutor!(GroupExecutor){

  //创建群接口
  @MessageId(MESSAGE.CMD_GREATE_GROUP_REQ)
  void createGroup(TransportContext ctx, MessageBuffer buffer) {
    auto req = new CreateGroupREQ();
    buffer.data.fromProtobuf!CreateGroupREQ(req);
    TransportSession msgClient = null;

    if (req.users.length > 1)
    {
       User[] users = ApplyService.getUsers(req.users, req.users[0]);
       int id = GroupService.addGroup(req,users);
       logInfo("createGroup ----- id : %d" , id);
       JoinGroup joinGroup = new JoinGroup;
       joinGroup.groupId = to!string(id);
       joinGroup.aliasName = req.groupName;
       joinGroup.member = users;
       joinGroup.validation = 0;

     ChatMapAction chatMapAction = new ChatMapAction;
     chatMapAction.chatId = to!string(id);
     chatMapAction.type = ChatMapActionType.CREATE;
     chatMapAction.manager = users[0].id;
     chatMapAction.timestamp = core.stdc.time.time(null);
     foreach(User u ; users)
     {
       chatMapAction.member ~= u.id;
     }
     msgClient =  MsgServerClient.getInstance().getForwardClient(id);
     msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array)); //向msgserver同步chatId对应关系列表

    foreach (User u ; joinGroup.member)
    {
       joinGroup.destination = u.id;
       msgClient = MsgServerClient.getInstance().getForwardClient(to!int(u.id));
       msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP,joinGroup.toProtobuf.array));//向群全部成员发送创建群回调
    }

    // InviteGroup inviteGroup = new InviteGroup;
    // inviteGroup.groupId = to!string(id);
    // inviteGroup.aliasName = req.aliasName;
    // inviteGroup.userId = req.userId;
    //  foreach(User u ; unAdopt)
    //  {
    //     inviteGroup.destination = u.id;
    //     msgClient = MsgServerClient.getInstance().getForwardClient(to!int(u.id));
    //     msgClient.send(new MessageBuffer(MESSAGE.CMD_INVITE_GROUP,inviteGroup.toProtobuf.array));
    //  }
    }
  }

    //邀请离线人员入群接口
   @MessageId(MESSAGE.CMD_OFFLINE_INVITE_GROUP)
   void putOfflineInviteGroup(TransportContext ctx, MessageBuffer buffer) {
     ApplyGroup applyGroup = new ApplyGroup;
     buffer.data.fromProtobuf!ApplyGroup(applyGroup);
     GroupService.addGroupApply(applyGroup, 0);
   }


  //处理群邀请接口
  @MessageId(MESSAGE.CMD_DEAL_GROUP_REQ)
  void dealGroupApply(TransportContext ctx, MessageBuffer buffer) {
    DealApplyGroup dealApplyGroup = new DealApplyGroup;
    buffer.data.fromProtobuf!DealApplyGroup(dealApplyGroup);

    if(GroupService.isExist(dealApplyGroup.userId, dealApplyGroup.groupId))
    {
        logInfo("ignorn dealGroupApply %s   group  %s", dealApplyGroup.userId, dealApplyGroup.groupId);
        return;
    }

    TransportSession msgClient = null;
    GroupService.updateGroupApplyStatus(dealApplyGroup.groupId, dealApplyGroup.fromId, dealApplyGroup.userId, dealApplyGroup.succeeded);
    if (dealApplyGroup.succeeded)
    {
      ChatMapAction chatMapAction = new ChatMapAction;
      chatMapAction.chatId = dealApplyGroup.groupId;
      chatMapAction.type = ChatMapActionType.ADD;
      chatMapAction.member = [dealApplyGroup.userId];
      chatMapAction.manager = dealApplyGroup.fromId;
      chatMapAction.timestamp = core.stdc.time.time(null);
      msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(dealApplyGroup.groupId));
      msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));

      auto em = defaultEntityManager();
      em.getTransaction().begin();
      User user = SearchUserService.selectUser(dealApplyGroup.userId,dealApplyGroup.fromId);
      GroupService.addGroupUser(dealApplyGroup.userId, to!int(dealApplyGroup.groupId), user.nickname, em);
      em.getTransaction().commit();
      em.close();

      JoinGroup joinGroup = GroupService.selectGroupInfo(dealApplyGroup.groupId,dealApplyGroup.userId);

      msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(dealApplyGroup.userId));
      msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP, joinGroup.toProtobuf.array));
    }
  }

  //退群接口
  @MessageId(MESSAGE.CMD_LEAVE_GROUP)
  void leaveGroup(TransportContext ctx, MessageBuffer buffer) {
    LeaveGroup leaveGroup = new LeaveGroup;
    buffer.data.fromProtobuf!LeaveGroup(leaveGroup);

    GroupService.deleteGroupUser(leaveGroup.fromId, leaveGroup.groupId);
    TransportSession msgClient = null;
    ChatMapAction chatMapAction = new ChatMapAction;
    chatMapAction.chatId = leaveGroup.groupId;
    chatMapAction.type = ChatMapActionType.DELETE;
    chatMapAction.member = [leaveGroup.fromId];
    msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(leaveGroup.groupId));
    msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
  }


  //解散群接口
  @MessageId(MESSAGE.CMD_CANCEL_GROUP)
  void cancelGroup(TransportContext ctx, MessageBuffer buffer) {
    CancelGroup cancelGroup = new CancelGroup;
    buffer.data.fromProtobuf!CancelGroup(cancelGroup);
    TransportSession msgClient = null;
    ChatMapAction chatMapAction = new ChatMapAction;
    chatMapAction.chatId = cancelGroup.groupId;
    chatMapAction.type = ChatMapActionType.DESTROY;
    chatMapAction.member = [];
    msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(cancelGroup.groupId));
    msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));

    GroupService.cancelGroup(cancelGroup.fromId, cancelGroup.groupId);
  }

  //踢出群接口
  @MessageId(MESSAGE.CMD_KICK_USER)
  void kickUser(TransportContext ctx, MessageBuffer buffer) {
    KickUser kickUser = new KickUser;
    buffer.data.fromProtobuf!KickUser(kickUser);

    if (!GroupService.isCreator(kickUser.fromId, kickUser.groupId))
    {
      return;
    }

    GroupService.deleteGroupUser(kickUser.userId, kickUser.groupId);

    TransportSession msgClient = null;
    ChatMapAction chatMapAction = new ChatMapAction;
    chatMapAction.chatId = kickUser.groupId;
    chatMapAction.type = ChatMapActionType.KICK;
    User user = new User;
    user.id = kickUser.userId;
    chatMapAction.member = [user.id];
    msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(kickUser.groupId));
    msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
  }

  @MessageId(MESSAGE.CMD_APPLY_GROUP)
  void applyGroup(TransportContext ctx, MessageBuffer buffer) {
    //ApplyGroup applyGroup = new ApplyGroup;
    //buffer.data.fromProtobuf!ApplyGroup(applyGroup);
    //
    //User user = SearchUserService.selectUser(applyGroup.fromId);
    //if (user is null)
    //{
    //  return;
    //}
    //TransportSession msgClient = null;
    //ChatMapAction chatMapAction = new ChatMapAction;
    //chatMapAction.chatId = applyGroup.groupId;
    //chatMapAction.type = ChatMapActionType.ADD;
    //chatMapAction.member = [user];
    //msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(applyGroup.groupId));
    //msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));
    //
    //GroupService.addGroupUser(applyGroup.fromId, to!int(applyGroup.groupId), applyGroup.username);
    //JoinGroup joinGroup = GroupService.selectGroupInfo(applyGroup.groupId,applyGroup.fromId);
    //
    //msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(applyGroup.fromId));
    //msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP, joinGroup.toProtobuf.array));
  }

  //更新群信息接口
  @MessageId(MESSAGE.CMD_UPDATE_GROUP_INFO)
  void updateGroupInfo(TransportContext ctx, MessageBuffer buffer) {
    auto req = new UpdateGroupInfo;
    buffer.data.fromProtobuf!UpdateGroupInfo(req);
    GroupService.updateGroupInfo(req);
  }

  //邀请入群接口
  @MessageId(MESSAGE.CMD_INVITE_GROUP)
  void groupInvite(TransportContext ctx, MessageBuffer buffer) {
      auto req = new InviteGroup;
      buffer.data.fromProtobuf!InviteGroup(req);
      TransportSession msgClient = null;
      string manager;
      foreach (string destination ; req.destination)
      {
        if (GroupService.isExist(destination, req.groupId))
        {
          return;
        }

        if(GroupService.needValidation(req.groupId,req.userId,manager))
        {

          ApplyGroup applyGroup = new ApplyGroup;
          applyGroup.fromId = req.userId;
          applyGroup.groupId = req.groupId;
          applyGroup.username = req.aliasName;
          applyGroup.newMember = destination;
          applyGroup.destination = manager;

          msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(manager));
          msgClient.send(new MessageBuffer(MESSAGE.CMD_APPLY_GROUP, applyGroup.toProtobuf.array));
          logInfo("groupInvite needValidation to %s",manager);
        }
        else
        {
          GroupService.groupInvite(req,destination);

          ChatMapAction chatMapAction = new ChatMapAction;
          chatMapAction.chatId = req.groupId;
          chatMapAction.type = ChatMapActionType.ADD;
          chatMapAction.member = [destination];
          chatMapAction.manager = req.userId;
          chatMapAction.timestamp = core.stdc.time.time(null);
          msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(req.groupId));
          msgClient.send(new MessageBuffer(MESSAGE.CMD_CHAT_MAP_ACTION, chatMapAction.toProtobuf.array));

          JoinGroup joinGroup = GroupService.selectGroupInfo(req.groupId,destination);

          msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(destination));
          msgClient.send(new MessageBuffer(MESSAGE.CMD_JOIN_GROUP, joinGroup.toProtobuf.array));
        }
      }

  }

  //设置群名称接口
  @MessageId(MESSAGE.CMD_SET_GROUP_NAME_REQ)
  void setGroupName(TransportContext ctx, MessageBuffer buffer) {
    auto req = new SetGroupNameREQ;
    buffer.data.fromProtobuf!SetGroupNameREQ(req);
    GroupService.setGroupName(req.groupId, req.groupName);

    auto msgClient =  MsgServerClient.getInstance().getForwardClient(to!int(req.groupId));
    msgClient.send(new MessageBuffer(MESSAGE.CMD_SET_GROUP_NAME_REQ, req.toProtobuf.array));
  }
}

